using System.Data;
using System.Linq.Expressions;
using Dapper;
using Gateway.IRepositories;
using MySqlConnector;
using SqlSugar;

namespace Gateway.Dapper;

public class DapperRepository : IQueryRepository
{
    /// <summary>
    /// 超时时间
    /// </summary>
    private readonly int timeOut = 200 * 10;

    /// <summary>
    /// 同步执行
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="func"></param>
    /// <returns></returns>
    private T Action<T>(Func<IDbConnection, T> func)
    {
        T data;
        using (IDbConnection db = new MySqlConnection(DapperExtension.GetConnectionString()))
        {
            data = func(db);
        }

        return data;
    }

    /// <summary>
    /// 异步执行
    /// </summary>
    /// <typeparam name="T"></typeparam>
    private async Task<T> ActionAsync<T>(Func<IDbConnection, Task<T>> func)
    {
        T data;
        using (IDbConnection db = new MySqlConnection(DapperExtension.GetConnectionString()))
        {
            data = await func(db);
        }

        return data;
    }

    public SqlSugarScope Db { get; }

    /// <summary>
    /// 查询一条记录
    /// </summary>
    public T QueryFirstOrDefault<T>(string sql, object param = null)
    {
        return Action(db => db.QueryFirstOrDefault<T>(sql, param, null, timeOut));
    }

    /// <summary>
    /// 查询一条记录 异步
    /// </summary>
    public async Task<T> QueryFirstOrDefaultAsync<T>(string sql, object param = null)
    {
        return await ActionAsync(db => db.QueryFirstOrDefaultAsync<T>(sql, param, null, timeOut));
    }

    /// <summary>
    /// 查询一条记录 动态类型 异步
    /// </summary>
    public async Task<dynamic> QueryFirstOrDefaultAsync(string sql, object param = null)
    {
        return await ActionAsync(db => db.QueryFirstOrDefaultAsync(sql, param, null, timeOut));
    }

    /// <summary>
    /// 查出多条记录的实体泛型集合
    /// </summary>
    /// <typeparam name="T">泛型T</typeparam>
    public IEnumerable<T> Query<T>(string sql, object param = null, IDbTransaction transaction = null,
        bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
    {
        if (commandTimeout == null)
        {
            commandTimeout = timeOut;
        }

        return Action(db => db.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType));
    }

    /// <summary>
    /// 查出多条记录的实体泛型集合 异步
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="sql">sql语句</param>
    /// <param name="param">查询参数</param>
    /// <param name="transaction">所使用的事务</param>
    /// <param name="commandTimeout">执行超时时间</param>
    /// <param name="commandType">语句类型</param>
    /// <returns></returns>
    public async Task<IEnumerable<T>> QueryAsync<T>(string sql, object param = null, IDbTransaction transaction = null,
        int? commandTimeout = null, CommandType? commandType = null)
    {
        if (commandTimeout == null)
        {
            commandTimeout = timeOut;
        }

        return await ActionAsync(db => db.QueryAsync<T>(sql, param, transaction, commandTimeout, commandType));
    }

    public async Task<List<T>> QueryListAsync<T>(string sql, object param = null, IDbTransaction transaction = null,
        int? commandTimeout = null,
        CommandType? commandType = null)
    {
        if (commandTimeout == null)
        {
            commandTimeout = timeOut;
        }

        var data = await ActionAsync(db => db.QueryAsync<T>(sql, param, transaction, commandTimeout, commandType));
        return data.ToList();
    }

    /// <summary>
    /// 查出多条记录的实体泛型集合 动态类型 异步
    /// </summary>
    /// <param name="sql">sql语句</param>
    /// <param name="param">查询参数</param>
    /// <param name="transaction">所使用的事务</param>
    /// <param name="commandTimeout">执行超时时间</param>
    /// <param name="commandType">语句类型</param>
    /// <returns></returns>
    public async Task<IEnumerable<object>> QueryAsync(string sql, object param = null,
        IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
    {
        if (commandTimeout == null)
        {
            commandTimeout = timeOut;
        }

        return await ActionAsync(db => db.QueryAsync(sql, param, transaction, commandTimeout, commandType));
    }
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="expression"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<T> FindAsync<T>(Expression<Func<T, bool>> expression)
    {
        throw new NotImplementedException();
    }
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="splitId"></param>
    /// <param name="expression"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<T> FindSplitAsync<T>(object splitId, Expression<Func<T, bool>> expression)
    {
        throw new NotImplementedException();
    }
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="expression"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<List<T>> GetListAsync<T>(Expression<Func<T, bool>> expression)
    {
        throw new NotImplementedException();
    }

    public Task<T> FindSplitAsync<T>(Expression<Func<T, bool>> expression)
    {
        throw new NotImplementedException();
    }
}